package com.dd.probe.web.util;

import com.dd.probe.common.pojo.param.SSHConnParam;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author liuxianmeng
 * @CreateTime 2024/10/12 6:23
 * @Description SSH工具类 获取服务器信息 使用之前需要先配置连接对象的信息sshCP sshCP不可为null
 */
@Slf4j
public class SSHUtil {

    public static void main(String[] args) {
        SSHUtil.configSSH(SSHConnParam.builder().IP("192.168.150.131")
                .port(22).username("root").password("zxcvbnml").build());
    }

    // JSch对象，用于执行SSH相关的操作。
    public static JSch jsch = new JSch();
    // 初始化配置参数 SSH连接信息
    public static SSHConnParam sshCP = SSHConnParam.builder().IP("127.0.0.1").port(22).username("root").password("zxcvbnml").build();;

    /**
     * 配置连接信息
     */
    public static void configSSH(SSHConnParam sshCP) {
        if(sshCP == null) throw new RuntimeException("SSHConnectionParam配置信息不可为空");
        SSHUtil.sshCP = sshCP;
    }

    /**
     * 执行SSH命令并返回命令输出 使用之前需要先配置连接对象的信息
     *
     * @param command  要执行的命令。
     * @return 命令执行的输出结果。
     */
    public static String execCommand(String command) {
        if(sshCP == null) {
            throw new RuntimeException("SSHConnectionParam配置信息不可为空,请先配置您要连接的对象信息");
        }

        Session session = null;
        ChannelExec channelExec = null;
        InputStream in = null;
        StringBuilder output = new StringBuilder();

        try {
            // 创建SSH会话
            session = jsch.getSession(sshCP.getUsername(), sshCP.getIP(), sshCP.getPort());
            session.setPassword(sshCP.getPassword());
            // 设置主机密钥验证策略为不严格，适用于测试环境
            session.setConfig("StrictHostKeyChecking", "no");
            // 连接到SSH服务器
            session.connect();

            // 打开执行通道
            channelExec = (ChannelExec) session.openChannel("exec");
            channelExec.setCommand(command);
            channelExec.setInputStream(null);
            in = channelExec.getInputStream();
            channelExec.setErrStream(System.err);
            channelExec.connect();

            // 读取命令输出
            byte[] buffer = new byte[1024];
            while (true) {
                while (in.available() > 0) {
                    int bytesRead = in.read(buffer, 0, buffer.length);
                    output.append(new String(buffer, 0, bytesRead));
                }
                if (channelExec.isClosed()) {
                    if (in.available() > 0) continue;
                    break;
                }
                try {
                    // 等待一段时间，避免频繁轮询
                    Thread.sleep(100);
                } catch (Exception e) {
                    log.error("Error while sleeping", e);
                }
            }
            channelExec.disconnect();
        } catch (IOException | JSchException e) {
            log.error("Error executing command", e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (channelExec != null) {
                    channelExec.disconnect();
                }
                if (session != null) {
                    session.disconnect();
                }
            } catch (IOException e) {
                log.error("Error closing resources", e);
            }
        }
        return output.toString();
    }
}
